package org.bet.utils;

import static org.easymock.EasyMock.reportMatcher;

import java.util.Collection;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.easymock.IArgumentMatcher;

public abstract class EasyMockUtils {
    public static <S,T> Map<S,T> eqMap(final Map<S,T> in) {
        reportMatcher(new IArgumentMatcher() {

            public void appendTo(StringBuffer out)
            {
                out.append("eqMap(");
                for(S key : in.keySet()) {
                    out.append("[").append(key).append("=>").append(in.get(key)).append("]");
                }
                out.append(")");
            }

            @SuppressWarnings("unchecked")
            public boolean matches(Object actual)
            {
                if(!(actual instanceof Map)) {
                    return false;
                }
                Map dummy = (Map)actual;
                for(S key : in.keySet()) {
                    if(!dummy.containsKey(key)) {
                        return false;
                    }
                    if(!dummy.get(key).equals(in.get(key))) {
                        return false;
                    }
                }
                //TODO - Check for values in new map NOT in existing map.
                return true;
            }
        });
        return null;
    }

    public static Properties eqProperties(final Properties in) {
        reportMatcher(new IArgumentMatcher() {

            public void appendTo(StringBuffer out)
            {
                out.append("eqProperties(");
                for(Object key : in.keySet()) {
                    out.append("[").append(key).append("=>").append(in.get(key)).append("]");
                }
                out.append(")");
            }

            @SuppressWarnings("unchecked")
            @Override
            public boolean matches(Object actual)
            {
                if(!(actual instanceof Properties)) {
                    return false;
                }
                Properties dummy = (Properties)actual;
                for(Object key : in.keySet()) {
                    if(!dummy.containsKey(key)) {
                        return false;
                    }
                    if(!dummy.get(key).equals(in.get(key))) {
                        return false;
                    }
                }
                //TODO - Check for values in new map NOT in existing map.
                return true;
            }
        });
        return null;
    }
    
    public static <T> Collection<T> eqCollection(final Collection<T> expectedColl, final String[] eltPropertyNames){
    	reportMatcher(new IArgumentMatcher() {
			private final Predicate predicate = PredicateUtils.equalCollectionPredicate(expectedColl, eltPropertyNames);
			
			@Override
			public boolean matches(Object actual) {
				return predicate.evaluate(actual);
			}
			
			@Override
			public void appendTo(StringBuffer buffer) {
				buffer.append("eqCollection[");
				buffer.append(expectedColl != null? StringUtils.join(expectedColl.iterator(), ",") : "");
				buffer.append("]");
				
			}
		});
    	
    	return null;
    }
    
    public static <T> T eqObjectProperties(final T expectedTarget, final String[] propertyNames){
    	reportMatcher(new IArgumentMatcher() {
			private final Predicate predicate = PredicateUtils.equalPropertiesPredicate(expectedTarget, propertyNames);
			@Override
			public boolean matches(Object actual) {
				return predicate.evaluate(actual);
			}
			
			@Override
			public void appendTo(StringBuffer buffer) {
				buffer.append("eqObjectProperties for " + expectedTarget.getClass().getSimpleName() + "[")
					.append(expectedTarget)
					.append("]");
			}
		});
    	return null;
    }
    
//	public static class ObjectPropertyMatcher<T> extends EqualPropertiesPredicate<T> implements IArgumentMatcher {
//		
//		public ObjectPropertyMatcher(T expectedTarget, String[] propertyNames) {
//			super(expectedTarget, propertyNames);
//		}
//
//
//		@SuppressWarnings("unchecked")
//		@Override
//		public boolean matches(Object arg) {
//			return evaluate(arg);
//		}
//
//		@Override
//		public void appendTo(StringBuffer buffer) {
//			buffer.append(expectedTarget.getClass().getSimpleName() + "[");
//			int size = readMethods.length;
//			try{
//				for(int i = 0; i < size; i++){
//					Object expectedProp = readMethods[i].invoke(expectedTarget, new Object[]{});
//					
//					buffer.append("(" + propertyNames[i] + "=>" + String.valueOf(expectedProp) + ")");
//					
//					if(i != (size - 1)){
//						buffer.append(",");
//					}
//				}
//				buffer.append("]");
//			}
//			catch(Exception e){
//				e.printStackTrace();
//			}
//		}		
//	}
	
}
